package com.ge.util;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Collection;

public class SynLinkedList {
	
	protected String strName = null;
	
	protected LinkedList mList = null;
	
	protected SynLinkedListListenerManage mAddManage = new SynLinkedListListenerManage();
	
	protected SynLinkedListListenerManage mRemoveManage = new SynLinkedListListenerManage();
	
	SynLinkedList(String strName) {
		this.strName = strName;
		mList = new LinkedList();
	}

	public String getName() {
		return strName;
	}

	public synchronized void addAddEventListener(AddEventListener mListener) {
		mAddManage.addListener(mListener);
	}
	
	public synchronized void removeAddEventListener(AddEventListener mListener) {
		mAddManage.removeListener(mListener);
	}

	public synchronized void addRemoveEventListener(RemoveEventListener mListener) {
		mRemoveManage.addListener(mListener);
	}
	
	public synchronized void removeRemoveEventListener(RemoveEventListener mListener) {
		mRemoveManage.removeListener(mListener);
	}
	
	public void addFirst(Object o) {
		synchronized (mList) {
			mAddManage.eventBefore(AddEventListener.ADD_FIRST, this, o);
			
			mList.addFirst(o);
			mList.notifyAll();
			
			mAddManage.eventAfter(AddEventListener.ADD_FIRST, this, o);
		}
	}

	public void addLast(Object o) {
		synchronized (mList) {
			mAddManage.eventBefore(AddEventListener.ADD_LAST, this, o);
			
			mList.addLast(o);
			mList.notifyAll();
			
			mAddManage.eventAfter(AddEventListener.ADD_LAST, this, o);
		}
	}

	public void addAll(Collection c) {
		synchronized (mList) {
			mAddManage.eventBefore(AddEventListener.ADD_LAST_ALL, this, c);
			
			mList.addAll(c);
			mList.notifyAll();
			
			mAddManage.eventAfter(AddEventListener.ADD_LAST_ALL, this, c);
		}
	}
	
	public int getSize() {
		return mList.size();
	}

	public void clear() {
		synchronized (mList) {
			mList.clear();
		}
	}
	
	public Object removeFirst() {
		Object obj = null;
		synchronized (mList) {
			while (mList.isEmpty()) {
				try {
					mList.wait();
	            } catch (InterruptedException e) {
	                e.printStackTrace();
	            }
			}
			
			mRemoveManage.eventBefore(RemoveEventListener.REMOVE_FIRST, this, null);
			
			obj = mList.removeFirst();
			
			mRemoveManage.eventAfter(RemoveEventListener.REMOVE_FIRST, this, obj);
		}

		return obj;
	}

	public Object[] removeAll() {
		Object[] obj = null;
		synchronized (mList) {
			
			mRemoveManage.eventBefore(RemoveEventListener.REMOVE_FIRST_ALL, this, null);
			
			obj = mList.toArray();
			
			mRemoveManage.eventAfter(RemoveEventListener.REMOVE_FIRST_ALL, this, obj);
			
			mList.clear();
		}

		return obj;
	}

	private static Map mapList = new HashMap();
	
	public static synchronized SynLinkedList getSynLinkedList(String strName) {
		SynLinkedList mList = (SynLinkedList)mapList.get(strName);
		if (mList == null) {
			mList = new SynLinkedList(strName);
			mapList.put(strName, mList);
		}
		
		return mList;
	}

	public static synchronized List getSynLinkedNameS() {
		Set keySet = mapList.keySet();
		Iterator it = keySet.iterator();
		List arr = new ArrayList();
		while (it.hasNext()) {
			arr.add(it.next());
		}
		return arr;
	}
}
